home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
escalant
/
escala21.lha
/
escalante2.1
/
src
/
gm
/
PVGraphElement.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-15
|
22KB
|
1,159 lines
//
// Copyright (C) 1993 Jeff McWhirter
//
//$PVGraphElement$
#include "PVGraphElement.h"
#include "PVRelation.h"
#include "Class.h"
#include "String.h"
#include "Set.h"
#include "ClassManager.h"
#ifdef USEGROUP
NewMetaImpl(PVGraphElement,PVGraphElement_BASE,(TP(protos),TP(InRels),TP(OutRels) ,T(eventMask),TP(name),TP(groups),0));
#endif
#ifndef USEGROUP
NewMetaImpl(PVGraphElement,PVGraphElement_BASE,(TP(protos),TP(InRels),TP(OutRels) ,T(eventMask),TP(name),0));
#endif
#define PVGraphElement_BASE GraphObject
ObjList * gVProtoList=0;
bool VInDie = FALSE;
static Set DefaultVDieSet;
Set * CurrentVDieSet =0;
void SetCurrentVDieSet(Set * s){
CurrentVDieSet =s;
}
void StartVDie(){VInDie = TRUE;}
void EndVDie(){
VInDie = FALSE;
KillVGraphElements();
}
void InVDie(bool f){VInDie = f;}
static Set GlobalVGraphElementSet;
static Set * CurrentVGraphElementSet;
void SetCurrentVGraphElementSet(Set *s){
CurrentVGraphElementSet =s;
}
Set * GetVGraphElementSet(){
return (CurrentVGraphElementSet?
CurrentVGraphElementSet:
&GlobalVGraphElementSet);
}
bool gVSetIO = TRUE;
void WriteOutVSet(OStream & o){
Object * obj;
int cnt =0;
Iter next(GetVGraphElementSet());
while (obj = next())
if(((PVGraphElement*)obj)->OkToWriteOut())
cnt ++;
o << cnt SP;
next.Reset(GetVGraphElementSet());
while (obj = next())
if(((PVGraphElement*)obj)->OkToWriteOut())
o << obj SP;
}
bool gVReadingIn = FALSE;
void ReadInVSet(IStream & o){
gVReadingIn = TRUE;
int cnt;
o >> cnt;
GetVGraphElementSet()->Empty(cnt);
Object * obj;
for(int i=0; i< cnt;i++){
o >> obj;
if(obj)
GetVGraphElementSet()->Add(obj);
}
gVReadingIn = FALSE;
}
Set * GetVDieSet(){return (CurrentVDieSet?CurrentVDieSet:&DefaultVDieSet);}
PVGraphElement::PVGraphElement(){
GetVGraphElementSet()->Add(this);
SetAdding(FALSE);
IfFalseDontWriteOutOriginal(TRUE);
IfFalseDontWriteOutClone(TRUE);
InRels= new ObjList();
OutRels= new ObjList();
eventMask = 0;
name = 0;
affectedByEvents=0;
protos =0;
#ifdef USEGROUP
groups =0;
#endif
}
#ifdef USEGROUP
VGroup * PVGraphElement::GetGroupWithId(int i){
if(!groups)return 0;
Iter next(groups);
VGroup*g;
while(g = (VGroup*)next())
if(g->GetId() == i) return g;
return 0;
}
#endif
void PVGraphElement::InitClone(){
INeedPtr(this);
PVGraphElement_BASE::InitClone();
IfFalseDontWriteOutOriginal(TRUE);
GetVGraphElementSet()->Add(this);
SetDead(FALSE);
InRels= new ObjList();
OutRels= new ObjList();
eventMask = 0;
affectedByEvents=0;
#ifdef USEGROUP
if(groups){
ObjList * oldg = groups;
groups = new ObjList();
Iter next(oldg);
VGroup * g;
while(g = (VGroup*) next())
AddGroup((VGroup*)EscalanteClone(g));
}
#endif
}
void PVGraphElement::AddGroupRelation(PVRelation * r){
PropagateEvent(eAEventAddElement,this,(void*)r);
}
void * PVGraphElement::DoEvent2(Events event, PVGraphElement * elt, void * data, ObjList * list)
{
if(DoneEvent(event)) return 0;
bool mylist = FALSE;
ObjList l;
if(list == 0) list = GetEventList(event);
if(list == 0){
mylist= TRUE;
list = &l;
SetEventList(event,list);
}
if(list){
if(list->ContainsPtr((Object*)this))
return 0;
list->Add((Object*)this);
}
SetEvent(event);
DoEvent(event,elt,data);
ClearEvent(event);
if(mylist) ClearEventList(event);
return 0;
}
void * PVGraphElement::DoEvent(Events event,PVGraphElement * , void * data){
switch(event){
case eAEventDie: Die(); break;
case eAEventDieHint: if(gDoDieHints) Die(); break;
case eAEventCopyHint: if(gDoCopyHints) return (void*)Copy();
case eAEventCopy: return (void*)Copy();
case eAEventAddElement: AddElement((PVGraphElement * )data); break;
default: break;
}
return 0;
}
void * PVGraphElement::GetAttribute(int aid,DataType & type){
if(aid == ATTRID(PVGraphElement,name)){
type = eChar;
return (void*)name;
}
return PVGraphElement_BASE::GetAttribute(aid,type);
}
void PVGraphElement::ChangeAttribute(int aid, void * data, DataType type){
if(aid == ATTRID(PVGraphElement,name)){
char * n=0;
if(ChangeData(data,type,n))
SetName(n);
}
else PVGraphElement_BASE::ChangeAttribute(aid,data,type);
}
void PVGraphElement::SendAttributeChange(int aid, void * data,DataType type){
PVGraphElement_BASE::SendAttributeChange( aid, data, type);
if(SendingAttrChange()) return;
SendingAttrChange(TRUE);
PVRelation * r;
if(gDoFromHdAttrMap && InRels){
Iter next(InRels);
while( r = (PVRelation*) next()) {
if(!r->IsDead())
r->AttrChangeOnHd(aid, data, type);
}
}
if(gDoFromHdAttrMap && OutRels){
Iter next(OutRels);
while( r = (PVRelation*) next()) {
if(!r->IsDead())
r->AttrChangeOnTl(aid, data, type);
}
}
SendingAttrChange(FALSE);
}
void * PVGraphElement::PropagateEvent(Events event,Events notevents, PVGraphElement * e,void * data, ObjList * list){
if(!OkToPropagateEvent(event))
return 0;
//if(DoneEvent(event)) return 0;
bool mylist = FALSE;
ObjList l;
if(list == 0) list = GetEventList(event);
if(list == 0){
mylist= TRUE;
list = &l;
SetEventList(event,list);
}
if(e == 0) e = this;
list->Add((Object*)this);
SetEvent(event);
void * rv = PropagateEvent2(event, notevents,e,data, list);
ClearEvent(event);
if(mylist) ClearEventList(event);
return rv;
}
void * PVGraphElement::PropagateEvent2(Events event,Events notevents, PVGraphElement * e,void * data, ObjList * list){
PVRelation * r;
if(InRels){
Iter next(InRels);
while(r = (PVRelation *)next())
r->EventOccurenceOnHd(event,notevents,e,data,list);
}
if(OutRels){
Iter next(OutRels);
while(r = (PVRelation *)next())
r->EventOccurenceOnTl(event,notevents,e,data,list);
}
return 0;
}
PVGraphElement* PVGraphElement::Copy(){
if(Copied() || HaveIBeenCloned(this)) return 0;
bool iamfirst = StartCloning();
Copied(TRUE);
PVGraphElement * clone = (PVGraphElement*)EscalanteClone(this);
if(!clone) return 0;
clone->Copied(FALSE);
if(gDoCopyHints)
PropagateEvent((Events)(eAEventCopy|eAEventCopyHint),this);
else
PropagateEvent(eAEventCopy,this);
Copied(FALSE);
if(iamfirst) EndCloning();
return clone;
}
void PVGraphElement::SetDead(bool f){
if(f && !IsDead()) GetVDieSet()->Add((Object*)this);
else if(!f && IsDead()) GetVDieSet()->Remove((Object*)this);
PVGraphElement_BASE::SetDead(f);
}
void PVGraphElement::Die(){
if(IsDead()) return;
PVGraphElement_BASE::Die();
Send(0,eAEventDie,0);
if(gDoDieHints)
PropagateEvent((Events)(eAEventDie|eAEventDieHint),this);
else
PropagateEvent(eAEventDie,this);
MS_Die();
}
PVGraphElement::~PVGraphElement(){
#ifdef USEGROUP
if(groups) groups->FreeAll();
SafeDelete(groups);
#endif
if(!IsDead()) Die();
GetVGraphElementSet()->Remove(this);
GetVDieSet()->Remove(this);
if(InRels){
InRels-> ForEach(PVRelation,SetHead)(0);
}
if(OutRels){
OutRels->ForEach(PVRelation,SetTail)(0);
}
SafeDelete( InRels);
SafeDelete( OutRels);
}
PVGraphElement * PVGraphElement::GetPrototypeOfClass(class Class * c)
{
if(!protos) return 0;
Iter next(protos);
PVGraphElement * e;
PVGraphElement * close=0;
while(e = (PVGraphElement*) next())
{
if(e->IsA()->IsEqual(c))return e;
if(e->IsA()->isKindOf(c)) close = e;
}
return close;
}
OStream& PVGraphElement::PrintOn(OStream& s){
PVGraphElement_BASE::PrintOn(s);
if(!gVSetIO){
s << InRels SP;
s << OutRels SP;
}
s << protos SP;
s << affectedByEvents SP;
#ifdef USEGROUP
s << groups SP;
#endif
s.PrintString(name);
s SP;
return s;
}
IStream& PVGraphElement::ReadFrom(IStream& s){
PVGraphElement_BASE::ReadFrom(s);
GetVGraphElementSet()->Add(this);
if(!gVSetIO){
s >> InRels ;
s >> OutRels ;
}
else {
InRels = new ObjList();
OutRels = new ObjList();
}
s >> protos;
s >> affectedByEvents ;
#ifdef USEGROUP
s >> groups ;
#endif
s.ReadString(&name);
eventMask =0;
return s;
}
void PVGraphElement::AddInRelation(PVRelation *r){
if(!r) return;
if(!InRels) InRels = new ObjList();
InRels->Add((Object*)r);
#ifdef USEGROUP
if(!gVReadingIn && groups){//These brackets have to be here.
groups-> ForEach(VGroup,AddedInRelation)(r);
}
#endif
}
void PVGraphElement::RemoveInRelation(PVRelation *r){
if(!InRels) return;
InRels->RemovePtr((Object*)r);
#ifdef USEGROUP
if(groups){//These brackets have to be here.
groups-> ForEach(VGroup,RemovedInRelation)(r);
}
#endif
}
void PVGraphElement::AddOutRelation(PVRelation *r)
{
if(!r) return;
if(!OutRels) OutRels = new ObjList();
OutRels->Add((Object*)r);
#ifdef USEGROUP
if(!gVReadingIn && groups){//These brackets have to be here.
groups-> ForEach(VGroup,AddedOutRelation)(r);
}
#endif
}
void PVGraphElement::RemoveOutRelation(PVRelation *r)
{
if(!OutRels) return;
OutRels->RemovePtr((Object*)r);
#ifdef USEGROUP
if(groups){//These brackets have to be here.
groups-> ForEach(VGroup,RemovedOutRelation)(r);
}
#endif
}
void PVGraphElement::NewTail(PVRelation * r, PVGraphElement * elt,PVGraphElement* oldtl){
#ifdef USEGROUP
if(groups){//These brackets have to be here.
groups-> ForEach(VGroup,NewTail)(r,elt,oldtl);
}
#endif
}
void PVGraphElement::NewHead(PVRelation * r, PVGraphElement * elt,PVGraphElement* oldhd){
#ifdef USEGROUP
if(groups){
groups-> ForEach(VGroup,NewHead)(r,elt,oldhd);
}
#endif
}
void PVGraphElement::GetRelsWithDep(ObjList & l, Events events, DepTypes type,RDir dir){
ObjList * rlist = GetRelations(dir);
if(!rlist) return;
Iter next(rlist);
register PVRelation *r ;
while(r = (PVRelation*)next())
if(r->GetEventDep(events,type)) l.Add((Object*)r);
}
PVRelation * PVGraphElement::GetRelation(PVGraphElement * e, RDir dir, Class * c,bool isk){
if(c == 0) c = Meta(PVRelation);
ObjList * rlist = GetRelations(dir);
if(!rlist) return 0;
Iter next(rlist);
PVRelation *r ;
PVGraphElement * other;
while(r = (PVRelation*)next()) {
if((other = r->GetOtherElement(this)) && other==e){
if(isk){
if( r->IsA()->isKindOf(c))
return(r);
}
else if(r->IsA()->IsEqual(c))
return r;
}
}
return 0;
}
bool PVGraphElement::PFunc( VPropFunc func ,
void * funcdata ,
int maxhops ,
RDir dir,
VPathFunc path ,
void * pathdata,
ObjList * l,
int hopssofar
){
if(Propagating() || hopssofar >= maxhops) return TRUE;
if(l && l->ContainsPtr(this)) return TRUE;
ObjList myl;
if(!l) l = &myl;
hopssofar ++;
Propagating(TRUE);
register PVRelation * r;
register PVGraphElement * elt;
bool OkToContinue = TRUE;
bool ok = TRUE;
register PVGraphElement * root = (PVGraphElement*)this;
if((dir == eIn || dir == eInOut) && InRels){
Iter next(InRels);
while(r = (PVRelation*) next()){
elt = (PVGraphElement*)r->tl;
if(!path || path(root,r,elt,pathdata,hopssofar))
ok = func(root,r,elt,funcdata,hopssofar,OkToContinue);
if(!OkToContinue ) {Propagating(FALSE);return FALSE;}
if(ok && elt && hopssofar < maxhops)
if(!elt->PFunc(func,funcdata,maxhops,dir,path, pathdata,l,hopssofar))
{Propagating(FALSE);return FALSE;}
}
}
if((dir == eOut || dir == eInOut) && OutRels){
Iter next(OutRels);
while(r = (PVRelation*) next()){
elt = (PVGraphElement*)r->hd;
if(!path || path(root,r,elt,pathdata,hopssofar))
ok = func(root,r,elt,funcdata,hopssofar,OkToContinue);
if(!OkToContinue ) {Propagating(FALSE);return FALSE;}
if(ok && elt && hopssofar <= maxhops)
if(! elt->PFunc(func,funcdata,maxhops,dir,path, pathdata,l,hopssofar))
{Propagating(FALSE);return FALSE;}
}
}
Propagating(FALSE);
return TRUE;
}
bool ClassPath(PVGraphElement*, PVRelation* rel, PVGraphElement* target, void * data, int ){
if(!data) return TRUE;
TwoClassStruct *s = (TwoClassStruct*)data;
if(s->c1 && rel)
if(!rel->IsA()->isKindOf(s->c1)) return FALSE;
if(s->c2 && target)
if(!target->IsA()->isKindOf(s->c2)) return FALSE;
return TRUE;
}
bool PVGraphElement::PFunc(VPropFunc func ,
void * funcdata ,
Class* relc ,
Class*eltc,
int hops,
RDir dir){
TwoClassStruct s;
s.c1 = relc;
s.c2 = eltc;
bool result = PFunc(func,funcdata,hops,dir,ClassPath,(void*)&s);
return result;
}
void KillVGraphElements(){
PVGraphElement * o;
Iter next(GetVDieSet());
while(o = (PVGraphElement*)next()) {
GetVDieSet()->Remove(o);
if(o->IsDead())
SafeDelete(o);
}
}
PVRelation * PVGraphElement::GetDefaultRelation(PVGraphElement * tl,PVGraphElement * hd,Class * relclass)
{
PVGraphElement * phd, * ptl;
PVRelation * prel;
PVRelation *isaisk=0,*iskisk = 0;
if(relclass == 0) relclass = Meta(PVRelation);
ObjList dummy;
Iter next(&dummy);
ObjList * plist=0;
for(int cnt = 0; cnt < 2; cnt++){
if(cnt == 0) plist = protos;
else {
if(protos != gVProtoList)
plist = gVProtoList;
else plist =0;
}
if(plist){
next.Reset(plist);
while(prel = (PVRelation*)next()){
if( prel->IsA()->isKindOf(relclass)){
phd = prel->GetHead();
ptl = prel->GetTail();
if(phd && ptl){
if((hd && phd ->IsA()->IsEqual(hd->IsA())) || ! hd){
if((tl && ptl ->IsA()->IsEqual(tl->IsA()) ) || ! tl)
return (PVRelation*)EscalanteClone(prel);
if((tl && tl ->IsA()->isKindOf(ptl->IsA()) ) || ! tl)
isaisk = prel;
}
if((hd && hd ->IsA()->isKindOf(phd->IsA())) || ! hd) {
if((tl && ptl ->IsA()->IsEqual(tl->IsA()) ) || ! tl)
isaisk = prel;
else if((tl && tl ->IsA()->isKindOf(ptl->IsA()) ) || ! tl)
iskisk = prel;
}
}
}
}
}
}
if(isaisk) return (PVRelation*)EscalanteClone(isaisk);
else if(iskisk) return (PVRelation*)EscalanteClone(iskisk);
else return 0;
}
void PVGraphElement::AddElement(PVGraphElement * elt,PVRelation * rel){
if(elt == 0) return;
if(!elt->AddOnCloning())return;
if(AddOnlyIfHaveProto()) {
bool haveone = FALSE;
PVGraphElement * pelt;
if(protos) {
Iter next(protos);
while((pelt=(PVGraphElement*)next()) && ! haveone)
if(elt->IsA()->isKindOf(pelt->IsA()))
haveone = TRUE;
}
if(gVProtoList && !haveone && gVProtoList != protos) {
Iter next(gVProtoList);
while((pelt=(PVGraphElement*)next()) && ! haveone)
if(elt->IsA()->isKindOf(pelt->IsA()))
haveone = TRUE;
}
if(!haveone) return;
}
if(!rel){
rel = GetDefaultRelation(this,elt);
if(AddOnlyIfHaveDflt() && !rel) return;
}
if(!rel) rel = GetDefaultMemberOf();
if(rel){
rel->SetTailHead(this,elt);
PropagateEvent(eAEventAddElement,this,(void*)elt);
}
}
void PVGraphElement::AddElements(Set * list) {
if(!list) return;
Iter next(list);
PVGraphElement *e;
while(e = (PVGraphElement*)next()) AddElement(e);
}
void PVGraphElement::MoveRelation(PVRelation * r, RDir dir,bool tofront) {
MovePtr((Object*)r,GetRelations(dir),tofront);
}
void PVGraphElement::Pred( Class *relClass, Class * eltClass, PVRelation*& retRel,PVGraphElement*&retElt,bool risk, bool eisk){
if(!InRels) return;
if(!relClass) relClass = Meta(PVRelation);
if(!eltClass) eltClass = Meta(PVGraphElement);
Iter next(InRels);
register PVRelation * rel=0;
register PVGraphElement * elt=0;
while(rel = (PVRelation*)next())
if(!rel->IsDead()){
if((risk && rel->IsA()->isKindOf(relClass)) || rel->IsA()->IsEqual(relClass))
if(elt = rel->GetTail())
if((eisk && elt->IsA()->isKindOf(eltClass)) || elt->IsA()->IsEqual(eltClass)){
retElt = elt; retRel = rel; return;
}
}
}
void PVGraphElement::Succ( Class *relClass, Class * eltClass, PVRelation*&retRel,PVGraphElement*&retElt,bool risk, bool eisk){
if(!OutRels) return;
if(!relClass ) relClass = Meta(PVRelation);
if(!eltClass ) eltClass = Meta(PVGraphElement);
Iter next(OutRels);
register PVRelation * rel;
register PVGraphElement * elt;
while(rel = (PVRelation*)next())
if(!rel->IsDead()){
if((risk && rel->IsA()->isKindOf(relClass)) || rel->IsA()->IsEqual(relClass))
if(elt = rel->GetHead() )
if((eisk &&elt->IsA()->isKindOf(eltClass)) || elt->IsA()->IsEqual(eltClass)){
retElt = elt; retRel = rel; return;
}
}
}
PVGraphElement * PVGraphElement::Pred( Class *relClass, Class * eltClass, bool risk, bool eisk){
PVRelation * rel=0;
PVGraphElement * elt=0;
Pred(relClass,eltClass,rel,elt,risk,eisk);
return elt;
}
PVGraphElement * PVGraphElement::Succ(class Class *relClass, class Class * eltClass, bool risk, bool eisk){
PVRelation * rel=0;
PVGraphElement * elt=0;
Succ(relClass,eltClass,rel,elt,risk,eisk);
return elt;
}
PVRelation * PVGraphElement::RelPred( Class *relClass, Class * eltClass, bool risk, bool eisk){
PVRelation * rel=0;
PVGraphElement * elt=0;
Pred(relClass,eltClass,rel,elt,risk,eisk);
return rel;
}
PVRelation * PVGraphElement::RelSucc(class Class *relClass, class Class * eltClass, bool risk, bool eisk){
PVRelation * rel=0;
PVGraphElement * elt=0;
Succ(relClass,eltClass,rel,elt,risk,eisk);
return rel;
}
#ifdef USEGROUP
NewMetaImpl(VOkToAdd,Object,(0));
NewMetaImpl(VRelXElt,VOkToAdd,(0));
NewMetaImpl(VGroup,Object,(TP(elts),0));
NewMetaImpl(VRelGroup,VGroup,(0));
NewMetaImpl(VEltGroup,VGroup,(0));
VGroup::~VGroup(){
PVGraphElement * prev =0;
PVGraphElement * next =0;
PVRelation * tr;
if(elts && firstProto){
next=(PVGraphElement*)elts->First();
prev = theelt;
if(prev && next){
tr=prev->GetRelation(next,eOut,firstProto->IsA(),FALSE);
if(tr) tr->Die();
}
}
if(elts&& relProto){
PVRelation * tr;
Iter iter(elts);
while(next = (PVGraphElement*)iter()){
next->RemoveObserver(this);
if(prev && next){
tr=prev->GetRelation(next,eOut,relProto->IsA(),FALSE);
if(tr)
tr->Die();
}
prev = next;
}
}
SafeDelete(elts);
}
OStream& VGroup:: PrintOn(OStream&o){
Object::PrintOn(o);
o << id SP;
o << relProto SP;
o << firstProto SP;
o << elts SP;
o << criteria SP;
return o;
}
IStream& VGroup::ReadFrom(IStream&o){
Object::ReadFrom(o);
o >> id;
o >> relProto;
o >> firstProto;
o >> elts;
o >> criteria;
return o;
}
IStream& VOkToAdd::ReadFrom(IStream&o){
Object::ReadFrom(o);
o >> Enum(dir) ;
return o;
}
OStream& VOkToAdd::PrintOn(OStream&o){
Object::PrintOn(o);
o << dir SP;
return o;
}
IStream& VRelXElt::ReadFrom(IStream&o){
VOkToAdd::ReadFrom(o);
if(!gClassManager)gClassManager = new ClassManager();
char * rn = 0;
char * en = 0;
o.ReadString(&rn);
o.ReadString(&en);
if(rn) relc = gClassManager->Find(rn);
if(en) eltc = gClassManager->Find(en);
return o;
}
OStream& VRelXElt::PrintOn(OStream&o){
VOkToAdd::PrintOn(o);
char * rn = relc?relc->Name():0;
char * en = eltc?eltc->Name():0;
o.PrintString(rn); o SP;
o.PrintString(en); o SP;
return o;
}
void VGroup::AddElement(PVGraphElement*elt){
if(elts == 0) elts = new ObjList();
else if(elts->Contains(elt)) return;
elt->AddObserver(this);
PVGraphElement * last = (PVGraphElement*)elts->Last();
elts->Add(elt);
if(last)
Connect(last,elt);
else if(theelt && firstProto){
PVRelation * newrel = (PVRelation*) EscalanteClone(firstProto);
theelt->AddGroupRelation(newrel);
newrel->SetTailHead(theelt,elt);
}
}
void VGroup::RemoveElement(PVGraphElement * elt){
if(!elt || !elts) return;
if(!elts->Contains(elt)) return;
elt->RemoveObserver(this);
PVRelation *prev,*next,*tr,*first=0;
if( ((Object*)elt) == elts->First() && theelt && firstProto){
first=theelt->GetRelation(elt,eOut,firstProto->IsA(),FALSE);
// if(first) first->SetHead(0);
}
if(elts->Size() == 1) {
elts->Remove(elt);
if(first) first->Die();
return;
}
//Find the previous and the next elements
prev = (PVRelation*) elts->BeforePtr(elt);
next = (PVRelation*)elts->AfterPtr(elt);
elts->Remove(elt);
if(prev && relProto){
tr=prev->GetRelation(elt,eOut,relProto->IsA(),FALSE);
if(tr) tr->Die();
}
if(next && relProto){
tr=elt->GetRelation(next,eOut,relProto->IsA(),FALSE);
if(tr) tr->Die();
}
if(prev && next) Connect(prev,next);
if(first && theelt && (prev = (PVRelation*)elts->First()))
first->SetHead(prev);
}
void VRelGroup::AddedRelation(PVRelation * r,RDir dir){
if(!r) return;
if(criteria){
if(dir == eOut){
if(!criteria->OutRelationOk(r)) return;
}
else {
if(!criteria->InRelationOk(r)) return;
}
}
AddElement((PVGraphElement*)r);
}
void VEltGroup::RemovedInRelation(PVRelation * r){
if(r)RemoveElement((PVGraphElement*)r->GetHead());
}
void VEltGroup::RemovedOutRelation(PVRelation * r){
if(r)RemoveElement((PVGraphElement*)r->GetHead());
}
void VEltGroup::AddedInRelation(PVRelation * r){
if(r) NewTail(r, r->GetTail(),0);
}
void VEltGroup::AddedOutRelation(PVRelation * r){
if(r)NewHead(r,r->GetHead(),0);
}
void VEltGroup::NewElt(RDir dir,PVRelation *r ,PVGraphElement* newelt,PVGraphElement* oldelt ){
RemoveElement(oldelt);
if(!newelt) return;
if(criteria){
if(dir == eOut){
if(!criteria->HeadOk(newelt,r)) return;
}
else {
if(!criteria->TailOk(newelt,r)) return;
}
}
AddElement((PVGraphElement*)newelt);
}
void VGroup::Connect(PVGraphElement * e1,PVGraphElement * e2){
if(e1 && e2 && relProto){
PVRelation * newrel = (PVRelation*) EscalanteClone(relProto);
if(theelt) theelt->AddGroupRelation(newrel);
newrel->SetTailHead(e1,e2);
}
}
void VGroup::DoObserve(int id, int part, void *d , Object *op){
if(part == eAEventDie && op && elts && elts->Contains(op))
RemoveElement((PVGraphElement*)op);
else if(part == cPartSenderDied && op && elts && elts->Contains(op))
elts->Remove(op);
else Object::DoObserve(id,part,d,op);
}
bool VRelXElt::HeadOk(PVGraphElement * hd,PVRelation * r){
if(!hd) return FALSE;
if(!OutRelationOk(r)) return FALSE;
if(eltc) return hd->IsA()->isKindOf(eltc);
return TRUE;
}
bool VRelXElt::TailOk(PVGraphElement * tl,PVRelation * r){
if(!tl) return FALSE;
if(!InRelationOk(r)) return FALSE;
if(eltc) return tl->IsA()->isKindOf(eltc);
return TRUE;
}
bool VRelXElt::InRelationOk(PVRelation * r){
if(!r) return FALSE;
if(!VOkToAdd::InRelationOk(r) ) return FALSE;
if(relc) return r->IsA()->isKindOf(relc);
else return TRUE;
}
bool VRelXElt::OutRelationOk(PVRelation * r){
if(!r) return FALSE;
if(!VOkToAdd::OutRelationOk(r) ) return FALSE;
if(relc) return r->IsA()->isKindOf(relc);
else return TRUE;
}
#endif USEGROUP